home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / util / pack / xpk_Source.lha / xpk_Source / xpkmaster / open.c < prev    next >
C/C++ Source or Header  |  1998-11-09  |  15KB  |  475 lines

  1. #ifndef XPKMASTER_OPEN_C
  2. #define XPKMASTER_OPEN_C
  3.  
  4. /* Routinesheader
  5.  
  6.     Name:        open.c
  7.     Main:        xpkmaster
  8.     Versionstring:    $VER: open.c 1.19 (30.10.1998)
  9.     Author:        SDI
  10.     Distribution:    Freeware
  11.     Description:    Opening and initialisation routines for XPK files
  12.  
  13.  1.0   06.10.96 : first real version
  14.  1.1   28.10.96 : reincluded A4 support
  15.  1.2   03.03.97 : added Prefs, corrected length recognition
  16.  1.3   07.03.97 : fixed prefs handling, new features
  17.  1.4   09.03.97 : added DEBUG statement
  18.  1.5   28.03.97 : auto decrunch password
  19.  1.6   29.03.97 : fixed prefs stuff, moved getinlen into hooks
  20.  1.7   31.03.97 : changed the password stuff
  21.  1.8   19.12.97 : added xfdmaster.library support
  22.  1.9   22.12.97 : fixed auto password problem
  23.  1.10  27.12.97 : fixed GetPassword error
  24.  1.11  09.01.98 : better key handling
  25.  1.12  21.01.98 : added password verification for packing
  26.  1.13  24.01.98 : fixed xfdmaster support a bit
  27.  1.14  17.02.98 : fixe long file problem added in last version
  28.  1.15  21.02.98 : uses new style register definition
  29.  1.16  26.03.98 : some optimizations
  30.  1.17  26.08.98 : may skip reading insize for packing, when no inhook
  31.  1.18  13.09.98 : removed PP stuff
  32.  1.19  30.10.98 : some changes for seek support
  33. */
  34.  
  35. #include <xpk/xpkprefs.h>
  36. #include <exec/memory.h>
  37. #include <proto/exec.h>
  38. #include <proto/dos.h>
  39. #include <proto/xpkmaster.h>
  40. #include <proto/xpksub.h>
  41. #include <proto/xfdmaster.h>
  42. #include "xpkmaster.h"
  43. #include "texts.h"
  44.  
  45. static const struct XpkInfo DONTInfo = { 1,0,0,1,"DONT","Copy",
  46. 0, 0x55534552, XPKIF_PK_CHUNK|XPKIF_UP_CHUNK, DEFAULTCHUNKSIZE, 1,
  47. DEFAULTCHUNKSIZE,0,0,0,0,100,0,0,0,0,0,0,0,0};
  48. /* XpkMode is not initialized! Should not be used anywhere */
  49.  
  50. static LONG xpkopenwrite(struct XpkBuffer **, struct TagItem *);
  51. static LONG GetPrefsPacker(struct XpkBuffer *);
  52. static LONG GetPassword(struct XpkBuffer *, struct TagItem *, ULONG);
  53. static struct XpkTypeData *BufRecog(ULONG, struct XpkBuffer *,
  54.   struct XpkPrefsSemaphore *);
  55.  
  56. XPK_ALLINONE ASM(LONG) xpkopen(REG(a0, struct XpkBuffer **xbufp),
  57. REG(a1, struct TagItem *tags), REG(d2, ULONG examine A4PROTO))
  58. {
  59.   struct XpkBuffer     *xbuf;
  60.   struct XpkStreamHeader *globhdr;
  61.   struct XpkFib         *fib;
  62.  
  63. #if defined(DEBUG) && defined(SUPPORT_A4)
  64.   DebugRunTime("xpkopen: A4 = %ld", a4);
  65. #elif defined (DEBUG)
  66.   DebugRunTime("xpkopen");
  67. #endif
  68.  
  69.   if(!(*xbufp = xbuf = initxbuf()))
  70.     return parseerrortags(tags, XPKERR_NOMEM);
  71.  
  72. #ifdef SUPPORT_A4
  73.   xbuf->xb_regA4 = a4;
  74. #endif
  75.  
  76.   globhdr = &xbuf->xb_Headers.h_Glob;
  77.   fib = &xbuf->xb_Fib;
  78.  
  79.   if(parsebuftags(xbuf, tags))
  80.     goto Abort;
  81.  
  82.   if(xbuf->xb_Flags & XMF_PACKING) /* Call pack open function */
  83.     return xpkopenwrite(xbufp, tags);
  84.  
  85.   if(!hookread(xbuf, XIO_READ, globhdr, 4)) /* Read first longword */
  86.   {
  87.     if(xbuf->xb_Result != XPKERR_TRUNCATED)
  88.       goto Abort;
  89.     /* else handle now as uncompressed file */
  90.   }
  91.  
  92.   /***************************** Standard XPK file **********************/
  93.   if(globhdr->xsh_Pack == XPK_COOKIE)
  94.   {
  95.     UWORD exthlen = 0;        /* size of extended header if present */
  96.     struct Library * XpkSubBase;
  97.  
  98.     xbuf->xb_Format = XPKMODE_UPSTD;
  99.  
  100.     /* Read rest of the global header */
  101.     if(!hookread(xbuf, XIO_READ, (STRPTR) globhdr + 4, sizeof(struct XpkStreamHeader) - 4))
  102.       goto Abort;
  103.  
  104.     if(hchecksum((STRPTR) globhdr, sizeof(struct XpkStreamHeader)))
  105.     {
  106.       xbuf->xb_Result = XPKERR_CHECKSUM;
  107.       goto Abort;
  108.     }
  109.  
  110.     if(globhdr->xsh_Flags & XPKSTREAMF_LONGHEADERS)
  111.       xbuf->xb_Headers.h_LocSize = sizeof(struct XpkChunkHdrLong);
  112.     else
  113.       xbuf->xb_Headers.h_LocSize = sizeof(struct XpkChunkHdrWord);
  114.  
  115.     if(globhdr->xsh_Flags & XPKSTREAMF_EXTHEADER)
  116.     {
  117.       if(!hookread(xbuf, XIO_READ, &exthlen, sizeof(UWORD)))
  118.     goto Abort;
  119.       if(!hookread(xbuf, XIO_READ, NULL, exthlen))
  120.     goto Abort;
  121.       exthlen += sizeof(UWORD);    /* for unwinding while XpkExamine */
  122.     }
  123.  
  124.     if(!hookread(xbuf, XIO_READ, &xbuf->xb_Headers.h_Loc,
  125.     xbuf->xb_Headers.h_LocSize))  /* first lochdr */
  126.       goto Abort;
  127.  
  128.     fib->xf_CCur = sizeof(struct XpkStreamHeader);
  129.     if(updatefib(xbuf))
  130.       goto Abort;
  131.     xbuf->xb_InLen = fib->xf_CLen;
  132.  
  133.     if(!(XpkSubBase = opensub(xbuf, globhdr->xsh_Type)))
  134.       goto Abort;
  135.  
  136.     if(globhdr->xsh_SubVrs > xbuf->xb_SubInfo->xi_LibVersion)
  137.     {
  138.       xbuf->xb_Result = XPKERR_OLDSUBLIB;
  139.       goto Abort;
  140.     }
  141.  
  142.     xbuf->xb_Prog.xp_Activity = xbuf->xb_SubInfo->xi_UnpackMsg ?
  143.       xbuf->xb_SubInfo->xi_UnpackMsg : strings[TXT_UNPACKING_UPPER];
  144.     xbuf->xb_Prog.xp_PackerName = xbuf->xb_SubInfo->xi_Name;
  145.     xbuf->xb_LastMsg = xbuf->xb_SubInfo->xi_UnpackedMsg ?
  146.       xbuf->xb_SubInfo->xi_UnpackedMsg : strings[TXT_UNPACKED];
  147.  
  148.     if(globhdr->xsh_Flags & XPKSTREAMF_PASSWORD)
  149.       fib->xf_Flags |= XPKFLAGS_PASSWORD;
  150.  
  151.     if(examine && !hookread(xbuf, XIO_SEEK, 0,
  152.     -(sizeof(struct XpkStreamHeader) + xbuf->xb_Headers.h_LocSize+exthlen)))
  153.       goto Abort;
  154.  
  155.     goto Exit;
  156.   }
  157.  
  158.   if(!hookread(xbuf, XIO_SEEK, 0, -xbuf->xb_RMsg.xmm_Size))
  159.     goto Abort; /* redo last read bytes */
  160.  
  161.   if(xbuf->xb_InLen == 0xFFFFFFFF)
  162.   {
  163.     if(!hookread(xbuf, XIO_TOTSIZE, 0, 0))    /* get input length */
  164.       goto Abort;
  165.     else if(xbuf->xb_RMsg.xmm_Size)
  166.       xbuf->xb_InLen = xbuf->xb_RMsg.xmm_Size;
  167.   }
  168.  
  169.   fib->xf_CLen = xbuf->xb_InLen;
  170.  
  171.   /**************************** xfdmaster file **************************/
  172.   if(xbuf->xb_Flags & XMF_XFD &&
  173.   (xbuf->xb_SubBase = OpenLibrary("xfdmaster.library", 38)))
  174.   {
  175.     struct xfdMasterBase *xfdMasterBase = (struct xfdMasterBase *) xbuf->xb_SubBase;
  176.     struct xfdBufferInfo *xbi;
  177.  
  178.     if(!(xbi = xbuf->xb_xfd = (struct xfdBufferInfo *) xfdAllocObject(XFDOBJ_BUFFERINFO)))
  179.       goto Abort;
  180.     if(!(xbi->xfdbi_SourceBuffer = hookread(xbuf, XIO_READ, 0, xbuf->xb_InLen)))
  181.       goto Abort;
  182.     xbi->xfdbi_SourceBufLen = xbuf->xb_InLen;
  183.     xbi->xfdbi_Flags = XFDFF_RECOGEXTERN|XFDFF_RECOGTARGETLEN|XFDFF_RECOGUSERTARGET;
  184.  
  185.     if(xfdRecogBuffer(xbi) && (xbi->xfdbi_PackerFlags & XFDPFF_DATA) &&
  186.     (LONG) xbi->xfdbi_FinalTargetLen != -1)
  187.     {
  188.       xbuf->xb_Format = XPKMODE_UPXFD;
  189.       if(xbi->xfdbi_PackerFlags & XFDPFF_PASSWORD)
  190.         xbuf->xb_Fib.xf_Flags |= XPKFLAGS_PASSWORD;
  191.       if(xbi->xfdbi_PackerFlags & XFDPFF_KEY16)
  192.         xbuf->xb_Fib.xf_Flags |= XPKFLAGS_KEY16;
  193.       if(xbi->xfdbi_PackerFlags & XFDPFF_KEY32)
  194.         xbuf->xb_Fib.xf_Flags |= XPKFLAGS_KEY32;
  195.       fib->xf_Type = XPKTYPE_PACKED;
  196.       fib->xf_ULen = xbi->xfdbi_FinalTargetLen;
  197.       fib->xf_NLen = xbi->xfdbi_MinTargetLen;
  198.       fib->xf_ID = XFD_COOKIE;
  199.       percentages(fib);
  200.       xbuf->xb_Prog.xp_Activity = strings[TXT_UNPACKING_UPPER];
  201.       xbuf->xb_Prog.xp_PackerName = "XFDMaster";
  202.       xbuf->xb_LastMsg = strings[TXT_UNPACKED];
  203.  
  204.       if(examine && !hookread(xbuf, XIO_SEEK, 0, -xbuf->xb_InLen))
  205.         goto Abort; /* return to start */
  206.  
  207. #ifdef DEBUG
  208.       DebugRunTime("xpkopen: XFD, InLen %ld, OutLen %ld, NLen %ld",
  209.       xbuf->xb_InLen, fib->xf_ULen, fib->xf_NLen);
  210. #endif
  211.       goto Exit;
  212.     } /* xfdRecogBuffer */
  213.  
  214.     if(!hookread(xbuf, XIO_SEEK, 0, -xbuf->xb_InLen))
  215.       goto Abort; /* return to start */
  216.   }
  217.  
  218.   /*************************** Uncompressed file ************************/
  219.   if(examine || xbuf->xb_Flags & XMF_PASSTHRU)        /* Unpacked */
  220.   {
  221.     xbuf->xb_Format = XPKMODE_UPUP;
  222.  
  223.     fib->xf_Type = XPKTYPE_UNPACKED;
  224.     fib->xf_ULen = xbuf->xb_InLen;
  225.     fib->xf_NLen = Min(DEFAULTCHUNKSIZE, xbuf->xb_InLen) + XPK_MARGIN;
  226.     fib->xf_ID = ROW_OF_MINUS;
  227.  
  228.     xbuf->xb_Prog.xp_Activity = strings[TXT_READING];
  229.     xbuf->xb_Prog.xp_PackerName = "Master";
  230.     xbuf->xb_LastMsg = strings[TXT_READ];
  231.  
  232.     xbuf->xb_Result = XPKERR_OK;  /* if != 0 it was XPKERR_TRUNCATED */
  233.  
  234.     goto Exit;
  235.   }
  236.  
  237.   xbuf->xb_Result = XPKERR_NOTPACKED;    /* Can't unpack, can't passthru */
  238.  
  239. Abort:
  240.   *xbufp = 0;
  241.   return XpkClose((struct XpkFib *) xbuf);
  242.  
  243. Exit:
  244.   if(!examine && (
  245.   ((fib->xf_Flags & XPKFLAGS_PASSWORD) && !xbuf->xb_Password) ||
  246.   ((fib->xf_Flags & XPKFLAGS_KEY16) && !(xbuf->xb_Flags & XMF_KEY16)) ||
  247.   ((fib->xf_Flags & XPKFLAGS_KEY32) && !(xbuf->xb_Flags & XMF_KEY32)))
  248.   && (xbuf->xb_Result = GetPassword(xbuf, tags, FALSE)))
  249.       goto Abort;
  250.  
  251.   return XPKERR_OK;
  252. }
  253.  
  254. /***************************** Open for packing *************************/
  255. static LONG xpkopenwrite(struct XpkBuffer **xbufp, struct TagItem *tags)
  256. {
  257.   struct XpkBuffer        *xbuf        = *xbufp;
  258.   struct XpkStreamHeader    *globhdr    = &xbuf->xb_Headers.h_Glob;
  259.   struct Library        *XpkSubBase;
  260.   LONG                 res;
  261.  
  262.   xbuf->xb_Format = XPKMODE_PKSTD;
  263.  
  264.   if(xbuf->xb_InLen == 0xFFFFFFFF && xbuf->xb_RHook)
  265.   {
  266.     if(!hookread(xbuf, XIO_TOTSIZE, 0, 0))    /* get input length */
  267.       return xbuf->xb_Result;
  268.     else if(xbuf->xb_RMsg.xmm_Size)
  269.       xbuf->xb_InLen = xbuf->xb_RMsg.xmm_Size;
  270.   }
  271.  
  272.   if(!(XpkSubBase = xbuf->xb_SubBase) &&  /* Do we know the sublib? */
  273.   (xbuf->xb_Result = GetPrefsPacker(xbuf)))
  274.     goto Abort; /* no sublib and no prefs packer finder */
  275.  
  276.   if(xbuf->xb_Password && !(xbuf->xb_SubInfo->xi_Flags & XPKIF_ENCRYPTION))
  277.   {
  278.     xbuf->xb_Result = XPKERR_NOCRYPT;
  279.     goto Abort;
  280.   }
  281.  
  282.   if(!xbuf->xb_Password && (xbuf->xb_SubInfo->xi_Flags & XPKIF_NEEDPASSWD))
  283.   { /* automatic password requester */
  284.     if((xbuf->xb_Result = GetPassword(xbuf, tags, TRUE)))
  285.       goto Abort;
  286.   }
  287.  
  288.   if(!(xbuf->xb_Flags & XMF_LOSSYOK) &&
  289.   xbuf->xb_SubInfo->xi_Flags & XPKIF_LOSSY)
  290.   {
  291.     xbuf->xb_Result = XPKERR_LOSSY;
  292.     goto Abort;
  293.   }
  294.  
  295.   if(xbuf->xb_PackingMode > 100)    /* Is packing mode valid? */
  296.     xbuf->xb_PackingMode = 100;        /* Use max */
  297.  
  298.   if(xbuf->xb_InLen != 0xFFFFFFFF)
  299.   {
  300.     if(!hookwrite(xbuf, XIO_TOTSIZE, 0, ROUNDLONG
  301.     (xbuf->xb_InLen + (xbuf->xb_InLen >> 5)) + (XPK_MARGIN<<1)))
  302.       goto Abort;
  303.   }
  304.  
  305.   /************************* Find the chunk size ************************/
  306.   if((xbuf->xb_ChunkSize == 0) &&
  307.   ((xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_DefPkInChunk) == 0))
  308.     xbuf->xb_ChunkSize = DEFAULTCHUNKSIZE;
  309.   if(xbuf->xb_ChunkSize < xbuf->xb_SubInfo->xi_MinPkInChunk)
  310.     xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_MinPkInChunk;
  311.   if((xbuf->xb_SubInfo->xi_MaxPkInChunk) &&
  312.   (xbuf->xb_ChunkSize > xbuf->xb_SubInfo->xi_MaxPkInChunk))
  313.     xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_MaxPkInChunk;
  314.  
  315.   /************************ Prepare global header ***********************/
  316.   globhdr->xsh_Pack = 0;        /* Initialize the global header */
  317.   globhdr->xsh_Type = xbuf->xb_SubID;
  318.  
  319.   if(xbuf->xb_ChunkSize > 65000) /* (0xFFFF-XPK_MARGIN) and some bytes security */
  320.     globhdr->xsh_Flags |= XPKSTREAMF_LONGHEADERS;
  321.   if(xbuf->xb_Password)
  322.     globhdr->xsh_Flags |= XPKSTREAMF_PASSWORD;
  323.  
  324.   xbuf->xb_Headers.h_LocSize = globhdr->xsh_Flags & XPKSTREAMF_LONGHEADERS
  325.     ? sizeof (struct XpkChunkHdrLong)
  326.     : sizeof (struct XpkChunkHdrWord);
  327.  
  328.   memset(globhdr->xsh_Initial, 0xff, 16);    /* Read first 16 bytes */
  329.  
  330.   xbuf->xb_Prog.xp_Activity = xbuf->xb_SubInfo->xi_PackMsg ?
  331.   xbuf->xb_SubInfo->xi_PackMsg : strings[TXT_PACKING_UPPER];
  332.   xbuf->xb_Prog.xp_PackerName = xbuf->xb_SubInfo->xi_Name;
  333.   xbuf->xb_LastMsg = xbuf->xb_SubInfo->xi_PackedMsg ?
  334.   xbuf->xb_SubInfo->xi_PackedMsg : strings[TXT_PACKED];
  335.  
  336. Abort:
  337.   xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen - xbuf->xb_Fib.xf_UCur,
  338.   xbuf->xb_ChunkSize);
  339.  
  340.   if((res = xbuf->xb_Result))
  341.     res = XpkClose((struct XpkFib *) xbuf);
  342.  
  343.   return res;
  344. }
  345.  
  346. typedef ASM(struct XpkTypeData *) (*RecogFunc) (REG(a0, STRPTR),
  347.     REG(a1, STRPTR), REG(d0, ULONG), REG(d1, ULONG),
  348.     REG(a2, struct TagItem *));
  349.  
  350. static LONG GetPrefsPacker(struct XpkBuffer *xbuf)
  351. {
  352.   LONG ret = XPKERR_UNKNOWN;
  353.   struct XpkPrefsSemaphore *sem;
  354.   ULONG bufsize;
  355.   struct XpkTypeData *td = 0;
  356.  
  357.   if((xbuf->xb_Flags & XMF_NOPREFS) || !xbuf->xb_RHook)
  358.     return XPKERR_BADPARAMS;
  359.   if(!(sem = GetPrefsSem()))
  360.     return XPKERR_NOFUNC;
  361.  
  362.   bufsize = Min(xbuf->xb_InLen, sem->xps_RecogSize);
  363.  
  364.   if(sem->xps_RecogFunc && (td = BufRecog(bufsize, xbuf, sem)) ==
  365.   (struct XpkTypeData *) 0xFFFFFFFF)
  366.     td = BufRecog(xbuf->xb_InLen, xbuf, sem);
  367.  
  368.   if(!td || td == (struct XpkTypeData *) 0xFFFFFFFF)
  369.     td = sem->xps_MainPrefs ? sem->xps_MainPrefs->xmp_DefaultType : 0;
  370.  
  371.   if(td)
  372.   {
  373.     if(td->xtd_Flags & XTD_NoPack)
  374.     {
  375.       xbuf->xb_Flags |= XMF_NOPACK;
  376.       xbuf->xb_SubInfo = (struct XpkInfo *) &DONTInfo;
  377.       ret = XPKERR_OK;
  378.     }
  379.     else if(!(td->xtd_Flags & XTD_ReturnError))
  380.     {
  381.       struct Library *XpkSubBase;
  382.       struct XpkInfo *subinfo;
  383.  
  384.       if((XpkSubBase = opensub(xbuf, td->xtd_StdID)))
  385.       {
  386.     ret = XPKERR_OK;
  387.         subinfo = XpksPackerInfo();
  388.  
  389.         xbuf->xb_ChunkSize = td->xtd_ChunkSize;
  390.         xbuf->xb_PackingMode = ( td->xtd_Mode ? td->xtd_Mode :
  391.           subinfo->xi_DefMode);
  392. //    if(!(xbuf->xb_Password) && td->xtd_Password && 
  393. //    (xbuf->xb_PasswordSize = strlen(td->xtd_Password)))
  394. //    {
  395. //      /* we need a buffer including end byte! --> ++size */
  396. //      if(!(xbuf->xb_Password = (STRPTR)
  397. //      AllocMem(++xbuf->xb_PasswordSize, MEMF_PUBLIC)))
  398. //        ret = XPKERR_NOMEM;
  399. //        else
  400. //      {
  401. //        xbuf->Flags |= XMF_OWNPASSWORD;
  402. //        CopyMem(td->xtd_Password, xbuf->xb_Password, xbuf->xb_PasswordSize);
  403. //      }
  404. //    }
  405.       }
  406.     }
  407.     else
  408.       ret = XPKERR_NOMETHOD;
  409.   }
  410.  
  411.   if(td->xtd_Memory && td->xtd_MemorySize)
  412.     FreeMem(td->xtd_Memory, td->xtd_MemorySize);
  413.  
  414.   ReleaseSemaphore((struct SignalSemaphore *) sem);
  415.   return ret;
  416. }
  417.  
  418. static LONG GetPassword(struct XpkBuffer *xbuf, struct TagItem *tags,
  419. ULONG verify)
  420. {
  421.  if(xbuf->xb_Flags & XMF_AUTOPASSWD)
  422.  {
  423.    if(xbuf->xb_Fib.xf_Flags & XPKFLAGS_KEY32)
  424.    {
  425.      xbuf->xb_Result = XpkPassRequestTags(XPK_Key32BitPtr,
  426.      &xbuf->xb_PassKey32, TAG_MORE, tags, TAG_DONE);
  427.      xbuf->xb_Flags |= XMF_KEY32;
  428.    }
  429.    else if(xbuf->xb_Fib.xf_Flags & XPKFLAGS_KEY16)
  430.    {
  431.      xbuf->xb_Result = XpkPassRequestTags(XPK_Key16BitPtr,
  432.      &xbuf->xb_PassKey16, TAG_MORE, tags, TAG_DONE);
  433.      xbuf->xb_Flags |= XMF_KEY16;
  434.    }
  435.    else
  436.    {
  437.      if(!(xbuf->xb_Password = (STRPTR) AllocMem(AUTO_PASS_SIZE, MEMF_PUBLIC)))
  438.        return XPKERR_NOMEM;
  439.      xbuf->xb_PasswordSize = AUTO_PASS_SIZE;
  440.      xbuf->xb_Flags |= XMF_OWNPASSWORD; /* must be freed later */
  441.  
  442.      xbuf->xb_Result = XpkPassRequestTags(XPK_PasswordBuf,
  443.      xbuf->xb_Password, XPK_PassBufSize, xbuf->xb_PasswordSize,
  444.      XPK_PassVerify, verify, TAG_MORE, tags, TAG_DONE);
  445.    }
  446.  
  447.    return xbuf->xb_Result;
  448.  }
  449.  return XPKERR_NEEDPASSWD;
  450. }
  451.  
  452. static struct XpkTypeData *BufRecog(ULONG bufsize, struct XpkBuffer *xbuf,
  453. struct XpkPrefsSemaphore *sem)
  454. {
  455.   STRPTR bufptr;
  456.   struct XpkTypeData *ret = 0;
  457.   struct TagItem tag[] = {
  458.   { XPK_FileName, 0},
  459.   { XPK_PackMode, 0},
  460.   { TAG_DONE, 0}};
  461.  
  462.   tag[0].ti_Data = (ULONG) xbuf->xb_Prog.xp_FileName;
  463.   tag[1].ti_Data = xbuf->xb_PackingMode;
  464.  
  465.   if((bufptr = (STRPTR) hookread(xbuf, XIO_READ, 0, bufsize)))
  466.   {
  467.     ret = (((RecogFunc) sem->xps_RecogFunc) (bufptr,
  468.     xbuf->xb_RMsg.xmm_FileName, bufsize, xbuf->xb_InLen, tag));
  469.     hookread(xbuf, XIO_SEEK, 0, -bufsize);
  470.   }
  471.   return ret;
  472. }
  473.  
  474. #endif /* XPKMASTER_OPEN_C */
  475.